import jwt from "jsonwebtoken";
import errorType from "../constants/error-types.ts";
import Userservice from "../service/user.service.ts";
import bcrypt from "@/utils/handle-password.ts";
import authService from "../service/auth.service.ts";
import config from "../app/config.ts";
import { Context, Next } from "koa";

// 核对用户名和密码
const verifyLogin = async (ctx: Context, next: Next) => {
  // 1.获取用户数据
  const { username, password } = ctx.request.body as API.userItem;
  // 2.判断用户名和密码是否为空
  if (!username || !password) {
    const error = new Error(errorType.USER_OR_PASSWORD_IS_NOT_EMPTY);
    return ctx.app.emit("error", error, ctx);
  }
  // 3.判断用户名是已经注册过的
  const result = await Userservice.getUserByUsername(username);
  const user = result;
  if (!user) {
    const error = new Error(errorType.USER_DOES_NOT_EXISIT);
    return ctx.app.emit("error", error, ctx);
  }
  // 4.判断用户登录密码是否和数据库中的密码相同(加密后);
  if (!(await bcrypt.verifyPassword(password, user.password))) {
    const error = new Error(errorType.PASSWORD_IS_ERROR);
    return ctx.app.emit("error", error, ctx);
  }

  // 校验成功后将用户数据返回
  ctx.user = user;
  await next();
};

// 校验用户是否登录成功 ,校验 token
const verifyAuth = async (ctx: Context, next: Next) => {
  console.log("用户登录token授权成功,欢迎您回来~");
  // 1.获取token
  const token = ctx.cookies.get("token");
  if (!token) {
    const error = new Error(errorType.NOT_AUTHORIZATION);
    return ctx.app.emit("error", error, ctx);
  }

  // 2.验证token
  try {
    const result = jwt.verify(token, config.PUBLICK_KEY, {
      algorithms: ["RS256"],
    });
    // 返回用户token令牌 result包含（id，username，iat，exp）
    ctx.state.user = result;
    await next(); //调用下一个中间件
  } catch (err) {
    const error = new Error(errorType.NOT_AUTHORIZATION);
    ctx.app.emit("error", error, ctx);
    console.log(errorType.NOT_AUTHORIZATION);
  }
};

const verfiyPermission = async (ctx: Context, next: Next) => {
  console.log("验证是否有权限middleware~");
  // 1.获取参数
  const [resourceKey] = Object.keys(ctx.params);
  const tableusername = resourceKey.replace("Id", "");
  const resourceId = ctx.params[resourceKey];
  const { id } = ctx.user;

  // 2.查询是否具备权限
  try {
    const isPermission = await authService.checkPermission(
      tableusername,
      resourceId,
      id
    );
    if (!isPermission) throw new Error();
  } catch (err) {
    const error = new Error(errorType.NOT_PERMISSION);
    return ctx.app.emit("error", error, ctx);
  }

  await next();
};

export default {
  verifyLogin,
  verifyAuth,
  verfiyPermission,
};
